package io.renren.common.redis;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * @ClassName: RedisService
 * @Description: Redis操作类
 */
@Service
public class RedisService {

	@Autowired
	private StringRedisTemplate stringRedisTemplate;

	@Resource(name = "stringRedisTemplate")
	private ValueOperations<String, String> valOpsStr;

	/**
	 * @Description :设置超时key,自增，用于统计
	 * 
	 */
	public void increment(String key, long value) {
		valOpsStr.increment(key, value);
	}

	/**
	 * @Description :存储
	 */
	public void set(String key, String value) {
		valOpsStr.set(key, value);
	}

	/**
	 * @Description :设置超时key,单位为秒钟
	 * 
	 */
	public void set(String key, String value, int offtime) {
		valOpsStr.set(key, value, offtime, TimeUnit.SECONDS);
	}
	
	/**
	 * @Description :设置超时key,单位为分钟
	 * 
	 */
	public void setExpireKeyMinutes(String key, String value, int offtime) {
		valOpsStr.set(key, value, offtime, TimeUnit.MINUTES);
	}


	public Boolean hasKey(String key) {
		return stringRedisTemplate.hasKey(key);
	}
	
	/**
	 * @Description :设置超时key,单位为小时
	 * 
	 */
	public void setExpireKeyHours(String key, String value, int offtime) {
		valOpsStr.set(key, value, offtime, TimeUnit.HOURS);
	}
	
	/**
	 * 获取key的过期时间  秒钟
	 * @param key
	 * @return
	 */
	public Long getExpireTime(String key) {
		return stringRedisTemplate.getExpire(key, TimeUnit.SECONDS);
	}

	/**
	 * @Description :获取
	 */
	public String get(String key) {
		return valOpsStr.get(key);
	}

	/**
	 * @Description :根据key移除
	 */
	public void remove(String key) {
		stringRedisTemplate.delete(key);
	}

	/**
	 * @Description :根据前缀得到value
	 * 
	 */
	public List<String> getByPrefix(String prefix) {
		Set<String> keys = stringRedisTemplate.keys(prefix + "*");
		if (keys == null || keys.size() == 0) {
			return null;
		}
		List<String> list = new ArrayList<>();
		for (String string : keys) {
			list.add(valOpsStr.get(string));
		}
		return list;
	}
	
	public Set<String> getByPrefix2(String prefix) {
		return  stringRedisTemplate.keys(prefix + "*");
	}

	/**
	 * @Description :根据前缀得到value
	 */
	public void delByPrefix(String prefix) {
		Set<String> keys = stringRedisTemplate.keys(prefix + "*");
		if (keys == null || keys.size() == 0) {
			return;
		}
		for (String key : keys) {
			stringRedisTemplate.delete(key);
		}
	}

	/**
	 * 存储set集合
	 * 
	 * @param key
	 * @param value
	 */
	public void setHashSet(String key, String value) {
		stringRedisTemplate.opsForSet().add(key, value);
	}

	/**
	 * 获取存储的set集合
	 * 
	 * @param key
	 * @return
	 */
	public Set<String> getHashSet(String key) {
		return stringRedisTemplate.opsForSet().members(key);
	}

	/**
	 * 根据key删除set集合中的某一条
	 * 
	 * @param key
	 * @param values
	 */
	public void removeHashSet(String key, String values) {
		stringRedisTemplate.opsForSet().remove(key, values);
	}

	/**
	 * 根据前缀获取set集合
	 * 
	 * @param prefix
	 * @return
	 */
	public Set<String> getSetByPrefix(String prefix) {
		Set<String> keyset = stringRedisTemplate.keys(prefix + "*");
		if (keyset == null || keyset.size() == 0) {
			return null;
		}
		Set<String> reipset = new HashSet<String>();
		for (String keys : keyset) {
			Set<String> ipset = stringRedisTemplate.opsForSet().members(keys);
			reipset.addAll(ipset);
		}
		return reipset;
	}

	
	public void setHashMap(String key, Object hashKey, Object value) {
		stringRedisTemplate.opsForHash().put(key.toString(), hashKey.toString(), value.toString());
	}
	
	public void setExpireHashMap(String key, Object hashKey, Object value,int offset) {
		stringRedisTemplate.opsForHash().put(key.toString(), hashKey.toString(), value.toString());
		stringRedisTemplate.expire(key, offset, TimeUnit.SECONDS);
		
	}

	public void deletHashMap(String key, Object hashKey) {
		stringRedisTemplate.opsForHash().delete(key.toString(), hashKey.toString());
	}

	public Object getHashMap(String key, Object hashKey) {
		return stringRedisTemplate.opsForHash().get(key, hashKey.toString());
	}
	
	public <T> T getHashMapClass(String key, Object hashKey,Class<T> clazz) {
		Object obj=stringRedisTemplate.opsForHash().get(key, hashKey.toString());
		if(obj!=null) {
			T t = JSONObject.parseObject(String.valueOf(obj), clazz);
			return t;
		}
		return null;
	}

	public List<Object> getHashMapList(String key) {
		Set<Object> hashkeys = stringRedisTemplate.opsForHash().keys(key);
		return stringRedisTemplate.opsForHash().multiGet(key, hashkeys);
	}
	
	public Set<Object> getHashMapKeyList(String key) {
		return stringRedisTemplate.opsForHash().keys(key);
	}

	/**
	 * 查询数据，并反序列化
	 * 
	 * @param key
	 * @param clazz
	 * @return
	 */
	public <T> List<T> getHashMapList(String key, Class<T> clazz) {
		List<T> list = new ArrayList<T>();
		Set<Object> hashkeys = stringRedisTemplate.opsForHash().keys(key);
		List<Object> objList = stringRedisTemplate.opsForHash().multiGet(key, hashkeys);
		if (objList != null && !objList.isEmpty()) {
			for (Object obj : objList) {
				T t = JSONObject.parseObject(String.valueOf(obj), clazz);
				list.add(t);
			}
		}
		return list;
	}

	/**
	 * 
	 * @desc 根据key获取整个hashmap
	 * @author abo
	 * @date 2018年7月11日 下午5:30:32
	 * @param key
	 * @return
	 */
	public Map<Object, Object> getHashMaps(String key) {
		return stringRedisTemplate.opsForHash().entries(key);
	}

	/**
	 * 向list左侧添加数据
	 * 
	 * @desc
	 * @author lj
	 * @param key
	 * @param obj
	 * @author 2018年10月2日
	 */
	public void leftPushList(String key, Object obj) {
		stringRedisTemplate.opsForList().leftPush(key, JSON.toJSONString(obj));
	}

	/**
	 * 向list右侧添加数据
	 * 
	 * @desc
	 * @author lj
	 * @param key
	 * @param obj
	 * @author 2018年10月2日
	 */
	public void rightPushList(String key, Object obj) {
		stringRedisTemplate.opsForList().rightPush(key, JSON.toJSONString(obj));
	}

	/**
	 * 从list左侧弹出一个数据
	 * 
	 * @desc
	 * @author lj
	 * @param key
	 * @param clazz
	 * @return
	 * @author 2018年10月2日
	 */
	public <T> T leftPopList(String key, Class<T> clazz) {
		String str = stringRedisTemplate.opsForList().leftPop(key);
		if (StringUtils.isNotBlank(str)) {
			return JSON.parseObject(str, clazz);
		}
		return null;
	}

	/**
	 * 从list左侧弹出一个数据
	 * 
	 * @desc
	 * @author lj
	 * @param key
	 * @param clazz
	 * @return
	 * @author 2018年10月2日
	 */
	public <T> T rightPopList(String key, Class<T> clazz) {
		String str = stringRedisTemplate.opsForList().rightPop(key);
		if (StringUtils.isNotBlank(str)) {
			return JSON.parseObject(str, clazz);
		}
		return null;
	}

	/**
	 * 从list中遍历数据
	 * 
	 * @desc
	 * @author lj
	 * @param key
	 * @param start
	 * @param limit
	 * @param clazz
	 * @return
	 * @author 2018年10月2日
	 */
	public <T> List<T> rangeList(String key, int start, int end, Class<T> clazz) {
		List<String> list = stringRedisTemplate.opsForList().range(key, start, end);
		List<T> list2 = new ArrayList<T>();
		if (list != null && list.size() > 0) {
			for (String str : list) {
				T t = JSON.parseObject(str, clazz);
				list2.add(t);
			}
		}
		return list2;
	}

	/**
	 * 像Zset中添加元素
	 * 
	 * @param key
	 * @param obj
	 * @param scores
	 * @return
	 */
	public Boolean zsetAdd(String key, Object obj, long scores) {
		return stringRedisTemplate.opsForZSet().add(key, JSON.toJSONString(obj), scores);
	}

	/**
	 * zset范围统计，在min到max中的数量
	 * 
	 * @param key
	 * @param min
	 * @param max
	 * @return
	 */
	public long zsetCount(String key, long min, long max) {
		return stringRedisTemplate.opsForZSet().count(key, min, max);
	}

	/**
	 * 获取zset中的范围值
	 * 
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public <T> List<T> zsetRange(String key, long min, long max, Class<T> clazz) {
		Set<TypedTuple<String>> set = stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max);
		List<T> list = new ArrayList<T>();
		if (set != null && set.size() > 0) {
			for (TypedTuple<String> type : set) {
				String value = type.getValue();
				T t = JSON.parseObject(value, clazz);
				list.add(t);
			}
		}
		return list;
	}

	/**
	 * 查询固定条数记录
	 * 
	 * @param key
	 * @param min
	 * @param max
	 * @param num
	 * @param clazz
	 * @return
	 */
	public <T> List<T> zsetRangeByScoreWithScores(String key, long min, long max, long count, Class<T> clazz) {
		// Set<TypedTuple<String>> set =
		// stringRedisTemplate.opsForZSet().rangeByScoreWithScores(key, min, max,num);
		Set<TypedTuple<String>> set = stringRedisTemplate.opsForZSet().reverseRangeByScoreWithScores(key, min, max, 0,
				count);
		List<T> list = new ArrayList<T>();
		if (set != null && set.size() > 0) {
			for (TypedTuple<String> type : set) {
				String value = type.getValue();
				T t = JSON.parseObject(value, clazz);
				list.add(t);
			}
		}
		return list;
	}
	

}